<template>
  <PageWrapper>
    <!-- 笔记 -->
    <CollapseContainer class="mt-5" title="emits">
      <markdown-viewer :value="getDoc()" />
    </CollapseContainer>

    <CollapseContainer class="mt-5" title="emits 用法示例">

      <Father/>

      <template #action>
        <Icon icon="ant-design:code-outlined" class="mr-1" :size="26" @click="openSource('基本类型', getBasic())" />
      </template>
    </CollapseContainer>


    <!-- 源码组件 -->
    <SourceDrawer ref="sourceDrawer" />
  </PageWrapper>
</template>
<script lang="ts" setup>
  import { CollapseContainer } from '@/components/Container';
  import { MarkdownViewer } from '@/components/Markdown';
  import { PageWrapper } from '@/components/Page';
  import SourceDrawer from '@/learn/SourceDrawer.vue';
  import { ref } from 'vue';
  import { Icon } from '@/components/Icon';
  import Father from "./Father.vue";

  // 定义子组件引用
  let sourceDrawer = ref<any>(null);
  function openSource(title: string, content: string) {
    sourceDrawer.value.open({ title, content, width: '60%' });
  }

</script>

<script lang="ts">
  function getDoc() {
    return `
* emits 只能用于子组件回调父组件的方法，可以实现将子组件的数据回传给父组件
* emits 和 props 的子传父方式非常相似，只是使用的方法存在细微差别

* 使用步骤:
  * 父组件将要传递的元素，以自定义方法方式进行传递: <label @xx-yy="abc" \/\>
  * 子组件通过 let emits = defineEmits([xxYy,xx]) 方法接收父组件自定义的方法，需要注意的是，方法名为 @xx-yy, 而不是 =后面的 abc。自动支持将 xx-yy 转换为 xxYy
  * 子组件通过 emits($method, $params) 回调用父组件传递的方法，实现将子组件的数据回传给父组件，或触发父组件的方法
  * 子组件中未通过 defineEmits 指定的方法，也会存入 $attrs 变量中。$attrs 用法和 props 中介绍的一样
* 适用场景:
  * 子传父: 新增表单，保存成功后，回调父组件的刷新列表方法。
  * 子组件需要通知父组件的场景
`;
  }

  function getBasic() {
    return `
### 父组件
\`\`\`html
<template>
  <div class="mt-5 bg-gray-300 p-5" title="父组件" :can-expan="false">
    <h3>父组件</h3>
    <ul>
      <li>普通对象 name:{{ name }}</li>
      <li>响应对象 car:{{ car }}</li>
      <li>接收子回调数据:{{ data }}</li>
    </ul>

    <Child @change-name="changeName" @change-car="changeCar" @send-data="setData" @ext-send="setData"/>
  </div>
</template>

\<script lang="ts" setup\>
  import Child from './Child.vue';
  import { ref } from 'vue';

  // 普通对象: 不具有响应式
  let name = ref<string>('zhangsan');

  // 响应对象: 子组件修改同步修改
  let car = ref({
    brand: '奔驰',
    price: 20,
  });

  // 存储子组件回调数据
  let data = ref();

  // 修改名称
  function changeName() {
    name.value +='~';
  }

  // 修改汽车信息
  function changeCar(){
    car.value.brand += '*-';
    car.value.price += 100;
  }

  // 接受子组件回调
  function setData(callBackData: string) {
    data.value = callBackData;
  }
\</script\>
\`\`\`

### 子组件
\`\`\`html
<template>
  <div class="mt-5 bg-blue-200 p-5" title="子组件" :can-expan="false">
    <h3>子组件</h3>
    <ul>
      <li>修改父组件的 name <Button @click="emits('changeName')">修改</Button> </li>
      <li>修改父组件的 car <Button @click="emits('changeCar')">修改</Button> </li>
      <li>
        <input v-model="inputData" />
        <Button @click="sendData">向父组件发送数据</Button>
      </li>
    </ul>
  </div>
</template>

\<script lang="ts" setup\>
  import { Button } from '@/components/Button';
  import { ref } from 'vue';

  // 定义要接收从父组件传来方法，方法名和 @xxx 保持一致，而不是和 ="aaa' 中的保持一致
  let emits = defineEmits(['changeName', 'changeCar', 'sendData']);

  let inputData = ref();

  function sendData() {
    emits('sendData', inputData)
  }

\</script\>
\`\`\`
`;
  }

</script>

<style lang="less" scoped>
  button {
    margin-left: 5px;
  }
</style>
